#include "mymainwindow.h"
#include "openclexception.h"

#include <QFileDialog>
#include <QMessageBox>
#include <QApplication>
#include <QRect>
#include <stdexcept>

/// Parameter:
/// Return:
/// Action: Setups the menus for the window.
void MyMainWindow::setup_menu()
{
    _fileMenu = menuBar()->addMenu(tr("File"));
    _filterMenu = menuBar()->addMenu(tr("Filters"));
    _aboutMenu = menuBar()->addMenu(tr("About"));

    _edgesSubMenu = _filterMenu->addMenu(tr("Find edges"));

    _fileOpenAction = new QAction(tr("Load image"), this);
    _fileSaveAction = new QAction(tr("Save image"), this);
    _openCLAction = new QAction(tr("OpenCL"), this);
    _quitAction = new QAction(tr("Quit"), this);
    _fileSaveAction->setEnabled(false);
    //_openCLAction->setCheckable(true);

    _aboutQtAction = new QAction(tr("About"), this);

    _blurAction = new QAction(tr("Blur"), this);
    _motionBlurAction = new QAction(tr("Motion blur"), this);
    _findHorizontalEdgesAction = new QAction(tr("Horizontal edges"), this);
    _findVerticalEdgesAction = new QAction(tr("Vertical edges"), this);
    _find45DegreeEdgesAction = new QAction(tr("45 degree edges"), this);
    _findAllEdgesAction = new QAction(tr("All edges"), this);
    _sharpenAction = new QAction(tr("Sharpen"), this);
    _excessiveEdgesAction = new QAction(tr("Excessive edges"), this);
    _embossAction = new QAction(tr("Emboss"), this);

    _fileMenu->addAction(_fileOpenAction);
    _fileMenu->addAction(_fileSaveAction);
    _fileMenu->addAction(_openCLAction);
    _fileMenu->addAction(_quitAction);

    _aboutMenu->addAction(_aboutQtAction);

    _filterMenu->addAction(_blurAction);
    _filterMenu->addAction(_motionBlurAction);
    _edgesSubMenu->addAction(_findHorizontalEdgesAction);
    _edgesSubMenu->addAction(_findVerticalEdgesAction);
    _edgesSubMenu->addAction(_find45DegreeEdgesAction);
    _edgesSubMenu->addAction(_findAllEdgesAction);
    _filterMenu->addAction(_sharpenAction);
    _filterMenu->addAction(_excessiveEdgesAction);
    _filterMenu->addAction(_embossAction);
    _filterMenu->setEnabled(false);

    connect(_fileOpenAction, SIGNAL(triggered()), this, SLOT(file_open_triggered()));
    connect(_fileSaveAction, SIGNAL(triggered()), this, SLOT(file_save_triggered()));
    connect(_openCLAction, SIGNAL(triggered()), this, SLOT(opencl_triggered()));
    connect(_quitAction, SIGNAL(triggered()), this, SLOT(close()));

    connect(_aboutQtAction, SIGNAL(triggered()), this, SLOT(about_qt_triggered()));

    connect(_blurAction, SIGNAL(triggered()), this, SLOT(blur_triggered()));
    connect(_motionBlurAction, SIGNAL(triggered()), this, SLOT(motion_blur_triggered()));
    connect(_findHorizontalEdgesAction, SIGNAL(triggered()), this, SLOT(find_horizontal_edges_triggered()));
    connect(_findVerticalEdgesAction, SIGNAL(triggered()), this, SLOT(find_vertical_edges_triggered()));
    connect(_find45DegreeEdgesAction, SIGNAL(triggered()), this, SLOT(find_45_degree_edges_triggered()));
    connect(_findAllEdgesAction, SIGNAL(triggered()), this, SLOT(find_all_edges_triggered()));
    connect(_sharpenAction, SIGNAL(triggered()), this, SLOT(sharpen_triggered()));
    connect(_excessiveEdgesAction, SIGNAL(triggered()), this, SLOT(excessive_edges_triggered()));
    connect(_embossAction, SIGNAL(triggered()), this, SLOT(emboss_triggered()));
}

/// Parameter:
/// Return:
/// Action: Setups the tool bar.
void MyMainWindow::setup_toolbar()
{
    _zoomInAction = new QAction(tr("+"), this);
    _zoomOutAction = new QAction(tr("-"), this);
    _zoomResetAction = new QAction(tr("0"), this);
    _swapAction = new QAction(tr("<-"), this);

    connect(_zoomInAction, SIGNAL(triggered()), this, SLOT(zoom_in_triggered()));
    connect(_zoomOutAction, SIGNAL(triggered()), this, SLOT(zoom_out_triggered()));
    connect(_zoomResetAction, SIGNAL(triggered()), this, SLOT(zoom_reset_triggered()));
    connect(_swapAction, SIGNAL(triggered()), this, SLOT(swap_triggered()));

    _toolBar = addToolBar("");
    _toolBar->addAction(_zoomInAction);
    _toolBar->addAction(_zoomOutAction);
    _toolBar->addAction(_zoomResetAction);
    _toolBar->addAction(_swapAction);
}

/// Parameter:
/// Return:
/// Action: Enables saving.
void MyMainWindow::enable_save()
{
    if (!_fileSaveAction->isEnabled())
        _fileSaveAction->setEnabled(true);
}

/// Parameter:
/// Return:
/// Action: Disables actions that could errors during transformation.
void MyMainWindow::disable_ui()
{
    _fileMenu->setEnabled(false);
    _filterMenu->setEnabled(false);
    _aboutMenu->setEnabled(false);

    _swapAction->setEnabled(false);
}

/// Parameter:
/// Return:
/// Action: Enables actions that could errors during transformation.
void MyMainWindow::enable_ui()
{
    _fileMenu->setEnabled(true);
    _filterMenu->setEnabled(true);
    _aboutMenu->setEnabled(true);

    _swapAction->setEnabled(true);
}

/// Parameter:
/// Return:
/// Action: Enable cancel button.
void MyMainWindow::enable_cancel()
{
    _cancelButton->setEnabled(true);
}

/// Parameter:
/// Return:
/// Action: Disable cancel button.
void MyMainWindow::disable_cancel()
{
    _cancelButton->setEnabled(false);
}

/// Parameter:
/// Return:
/// Action: Disable save.
void MyMainWindow::disable_save()
{
    _fileSaveAction->setEnabled(false);
}

/// Parameter:
/// Return:
/// Action: Shows a file dialog to pick an image.
///         Loads the image to the backend and to the central widget.
void MyMainWindow::file_open_triggered()
{
    QString fileName = QFileDialog::getOpenFileName(this, "Open file", "", "Images (*.bmp *.jpg)");

    if (fileName == "")
        return;

    try
    {
        _backend->load_image(fileName);
        _myWidget->set_original(_backend->get_original_image());
    }
    catch (const OpenCLException& ex)
    {
        QMessageBox::information(this, "OpenCL error",
                                 QString(ex.what()) + ". Code: " +
                                 QString::number(ex.error_code()));
        return;
    }
    catch (const std::runtime_error& ex)
    {
        QMessageBox::information(this, "Runtime error", ex.what());
        return;
    }
    catch (...)
    {
        QMessageBox::information(this, "Unexpected error", "Unexpected error, the program terminates");
        close();
    }

    if (!_filterMenu->isEnabled())
        _filterMenu->setEnabled(true);

    _fileSaveAction->setEnabled(false);
}

/// Parameter:
/// Return:
/// Action: Shows a file dialog to pick a directory to save the image.
void MyMainWindow::file_save_triggered()
{
    QString fileName = QFileDialog::getSaveFileName(this, "Save file", "", "Images (*.bmp *.jpg)");

    if (fileName == "")
        return;

    _backend->save(fileName);
}

/// Parameter:
/// Return:
/// Action: Shows a dialog to enable/disable OpenCL.
///         If OpenCL is enabled, the platform and device can be selected.
void MyMainWindow::opencl_triggered()
{
    std::vector<cl::Platform> platforms;
    try
    {
        _backend->avalaible_platforms(platforms);
    }
    catch (const OpenCLException& ex)
    {
        QMessageBox::information(this, "OpenCL error",
                                 QString(ex.what()) + ". Code: " +
                                 QString::number(ex.error_code()));
        return;
    }
    catch (const std::runtime_error& ex)
    {
        QMessageBox::information(this, "Runtime error", ex.what());
        return;
    }
    catch (...)
    {
        QMessageBox::information(this, "Unexpected error", "Unexpected error, the program terminates");
        close();
    }

    if (_openCLDialog == 0)
    {
        try
        {
            _openCLDialog = new OpenCLDialog(platforms);
        }
        catch (const OpenCLException& ex)
        {
            QMessageBox::information(this, "OpenCL error",
                                     QString(ex.what()) + ". Code: " +
                                     QString::number(ex.error_code()));
            return;
        }
        catch (const std::runtime_error& ex)
        {
            QMessageBox::information(this, "Runtime error", ex.what());
            return;
        }
        catch (...)
        {
            QMessageBox::information(this, "Unexpected error", "Unexpected error, the program terminates");
            close();
        }

    }
    if (_openCLDialog->exec())
    {
        if (_openCLDialog->is_enabled())
        {
            _label->setText(QString::fromStdString(_openCLDialog->selected_platform().getInfo<CL_PLATFORM_NAME>())
                            + "\n" +
                            QString::fromStdString(_openCLDialog->selected_device().getInfo<CL_DEVICE_NAME>()));

            _backend->set_platform(_openCLDialog->selected_platform());
            _backend->set_device(_openCLDialog->selected_device());
        }
        else
            _label->setText("No platform set, using sequential algorithm");

        try
        {
            _backend->set_parallel(_openCLDialog->is_enabled());
        }
        catch (const OpenCLException& ex)
        {
            QMessageBox::information(this, "OpenCL error",
                                     QString(ex.what()) + ". Code: " +
                                     QString::number(ex.error_code()));
            return;
        }
        catch (const std::runtime_error& ex)
        {
            QMessageBox::information(this, "Runtime error", ex.what());
            return;
        }
        catch (...)
        {
            QMessageBox::information(this, "Unexpected error", "Unexpected error, the program terminates");
            close();
        }
    }
}

/// Parameter:
/// Return:
/// Action: Shows a dialog about the Qt platform.
void MyMainWindow::about_qt_triggered()
{
    QMessageBox::aboutQt(this);
}

/// Parameter:
/// Return:
/// Action: Blur transformation.
///         Constructs a small image to be showed in the parameterizer dialog.
///         Shows the dialog.
///         Sets progress bar.
///         Disables UI elements.
///         Run the transformation.
///         Set the modified image and the data in the table.
///         Enables UI elements.
void MyMainWindow::blur_triggered()
{
    try
    {
        QImage im = _backend->get_original_image()->scaled(100, 100, Qt::AspectRatioMode::KeepAspectRatioByExpanding);

        BlurDialog d(im);
        if (d.exec())
        {
            int matrixWidth;
            float* matrix = d.get_filter_matrix(matrixWidth);

            _progressBar->setMinimum(_backend->progress_min());
            _progressBar->setMaximum(_backend->progress_max());

            TransformInfo info;
            disable_ui();
            enable_cancel();
            QImage* result = _backend->blur(matrix, matrixWidth, info);
            _myWidget->set_modified(result);
            _myWidget->add_info(info);

            if (result->isNull())
            {
                enable_ui();
                disable_cancel();
                disable_save();
            }
            else
            {
                enable_save();
                enable_ui();
                disable_cancel();
            }
        }
    }
    catch (const OpenCLException& ex)
    {
        QMessageBox::information(this, "OpenCL error",
                                 QString(ex.what()) + ". Code: " +
                                 QString::number(ex.error_code()));
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (const std::runtime_error& ex)
    {
        QMessageBox::information(this, "Runtime error", ex.what());
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (...)
    {
        QMessageBox::information(this, "Unexpected error", "Unexpected error, the program terminates");
        close();
    }
}

/// Parameter:
/// Return:
/// Action: Motion blur transformation.
///         Constructs a small image to be showed in the parameterizer dialog.
///         Shows the dialog.
///         Sets progress bar.
///         Disables UI elements.
///         Run the transformation.
///         Set the modified image and the data in the table.
///         Enables UI elements.
void MyMainWindow::motion_blur_triggered()
{
    try
    {
        QImage im = _backend->get_original_image()->scaled(100, 100, Qt::AspectRatioMode::KeepAspectRatioByExpanding);

        float matrix[81];
        MotionBlurDialog d(im);
        if (d.exec())
        {
            d.get_filter_matrix(matrix);

            _progressBar->setMinimum(_backend->progress_min());
            _progressBar->setMaximum(_backend->progress_max());

            TransformInfo info;
            disable_ui();
            enable_cancel();
            QImage* result = _backend->motion_blur(matrix, info);
            _myWidget->set_modified(result);
            _myWidget->add_info(info);

            if (result->isNull())
            {
                enable_ui();
                disable_cancel();
                disable_save();
            }
            else
            {
                enable_save();
                enable_ui();
                disable_cancel();
            };
        }
    }
    catch (const OpenCLException& ex)
    {
        QMessageBox::information(this, "OpenCL error",
                                 QString(ex.what()) + ". Code: " +
                                 QString::number(ex.error_code()));
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (const std::runtime_error& ex)
    {
        QMessageBox::information(this, "Runtime error", ex.what());
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (...)
    {
        QMessageBox::information(this, "Unexpected error", "Unexpected error, the program terminates");
        close();
    }
}

/// Parameter:
/// Return:
/// Action: Find horizontal edges transformation.
///         Sets progress bar.
///         Disables UI elements.
///         Run the transformation.
///         Set the modified image and the data in the table.
///         Enables UI elements.
void MyMainWindow::find_horizontal_edges_triggered()
{
    try
    {
        _progressBar->setMinimum(_backend->progress_min());
        _progressBar->setMaximum(_backend->progress_max());

        TransformInfo info;
        disable_ui();
        enable_cancel();
        QImage* result = _backend->find_horizontal_edges(info);
        _myWidget->set_modified(result);
        _myWidget->add_info(info);

        if (result->isNull())
        {
            enable_ui();
            disable_cancel();
            disable_save();
        }
        else
        {
            enable_save();
            enable_ui();
            disable_cancel();
        }
    }
    catch (const OpenCLException& ex)
    {
        QMessageBox::information(this, "OpenCL error",
                                 QString(ex.what()) + ". Code: " +
                                 QString::number(ex.error_code()));
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (const std::runtime_error& ex)
    {
        QMessageBox::information(this, "Runtime error", ex.what());
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (...)
    {
        QMessageBox::information(this, "Unexpected error", "Unexpected error, the program terminates");
        close();
    }
}

/// Parameter:
/// Return:
/// Action: Find vertical edges transformation.
///         Sets progress bar.
///         Disables UI elements.
///         Run the transformation.
///         Set the modified image and the data in the table.
///         Enables UI elements.
void MyMainWindow::find_vertical_edges_triggered()
{
    try
    {
        _progressBar->setMinimum(_backend->progress_min());
        _progressBar->setMaximum(_backend->progress_max());

        TransformInfo info;
        disable_ui();
        enable_cancel();
        QImage* result = _backend->find_vertical_edges(info);
        _myWidget->set_modified(result);
        _myWidget->add_info(info);

        if (result->isNull())
        {
            enable_ui();
            disable_cancel();
            disable_save();
        }
        else
        {
            enable_save();
            enable_ui();
            disable_cancel();
        }
    }
    catch (const OpenCLException& ex)
    {
        QMessageBox::information(this, "OpenCL error",
                                 QString(ex.what()) + ". Code: " +
                                 QString::number(ex.error_code()));
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (const std::runtime_error& ex)
    {
        QMessageBox::information(this, "Runtime error", ex.what());
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (...)
    {
        QMessageBox::information(this, "Unexpected error", "Unexpected error, the program terminates");
        close();
    }
}

/// Parameter:
/// Return:
/// Action: Find 45 degree edges transformation.
///         Sets progress bar.
///         Disables UI elements.
///         Run the transformation.
///         Set the modified image and the data in the table.
///         Enables UI elements.
void MyMainWindow::find_45_degree_edges_triggered()
{
    try
    {
        _progressBar->setMinimum(_backend->progress_min());
        _progressBar->setMaximum(_backend->progress_max());

        TransformInfo info;
        disable_ui();
        enable_cancel();
        QImage* result = _backend->find_45_degree_edges(info);
        _myWidget->set_modified(result);
        _myWidget->add_info(info);

        if (result->isNull())
        {
            enable_ui();
            disable_cancel();
            disable_save();
        }
        else
        {
            enable_save();
            enable_ui();
            disable_cancel();
        }
    }
    catch (const OpenCLException& ex)
    {
        QMessageBox::information(this, "OpenCL error",
                                 QString(ex.what()) + ". Code: " +
                                 QString::number(ex.error_code()));
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (const std::runtime_error& ex)
    {
        QMessageBox::information(this, "Runtime error", ex.what());
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (...)
    {
        QMessageBox::information(this, "Unexpected error", "Unexpected error, the program terminates");
        close();
    }
}

/// Parameter:
/// Return:
/// Action: Find all edges transformation.
///         Sets progress bar.
///         Disables UI elements.
///         Run the transformation.
///         Set the modified image and the data in the table.
///         Enables UI elements.
void MyMainWindow::find_all_edges_triggered()
{
    try
    {
        _progressBar->setMinimum(_backend->progress_min());
        _progressBar->setMaximum(_backend->progress_max());

        TransformInfo info;
        disable_ui();
        enable_cancel();
        QImage* result = _backend->find_all_edges(info);
        _myWidget->set_modified(result);
        _myWidget->add_info(info);

        if (result->isNull())
        {
            enable_ui();
            disable_cancel();
            disable_save();
        }
        else
        {
            enable_save();
            enable_ui();
            disable_cancel();
        }
    }
    catch (const OpenCLException& ex)
    {
        QMessageBox::information(this, "OpenCL error",
                                 QString(ex.what()) + ". Code: " +
                                 QString::number(ex.error_code()));
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (const std::runtime_error& ex)
    {
        QMessageBox::information(this, "Runtime error", ex.what());
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (...)
    {
        QMessageBox::information(this, "Unexpected error", "Unexpected error, the program terminates");
        close();
    }
}

/// Parameter:
/// Return:
/// Action: Sharpen transformation.
///         Sets progress bar.
///         Disables UI elements.
///         Run the transformation.
///         Set the modified image and the data in the table.
///         Enables UI elements.
void MyMainWindow::sharpen_triggered()
{
    try
    {
        _progressBar->setMinimum(_backend->progress_min());
        _progressBar->setMaximum(_backend->progress_max());

        TransformInfo info;
        disable_ui();
        enable_cancel();
        QImage* result = _backend->sharpen(info);
        _myWidget->set_modified(result);
        _myWidget->add_info(info);

        if (result->isNull())
        {
            enable_ui();
            disable_cancel();
            disable_save();
        }
        else
        {
            enable_save();
            enable_ui();
            disable_cancel();
        }
    }
    catch (const OpenCLException& ex)
    {
        QMessageBox::information(this, "OpenCL error",
                                 QString(ex.what()) + ". Code: " +
                                 QString::number(ex.error_code()));
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (const std::runtime_error& ex)
    {
        QMessageBox::information(this, "Runtime error", ex.what());
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (...)
    {
        QMessageBox::information(this, "Unexpected error", "Unexpected error, the program terminates");
        close();
    }
}

/// Parameter:
/// Return:
/// Action: Excessive edges transformation.
///         Sets progress bar.
///         Disables UI elements.
///         Run the transformation.
///         Set the modified image and the data in the table.
///         Enables UI elements.
void MyMainWindow::excessive_edges_triggered()
{
    try
    {
        _progressBar->setMinimum(_backend->progress_min());
        _progressBar->setMaximum(_backend->progress_max());

        TransformInfo info;
        disable_ui();
        enable_cancel();
        QImage* result = _backend->excessive_edges(info);
        _myWidget->set_modified(result);
        _myWidget->add_info(info);

        if (result->isNull())
        {
            enable_ui();
            disable_cancel();
            disable_save();
        }
        else
        {
            enable_save();
            enable_ui();
            disable_cancel();
        }
    }
    catch (const OpenCLException& ex)
    {
        QMessageBox::information(this, "OpenCL error",
                                 QString(ex.what()) + ". Code: " +
                                 QString::number(ex.error_code()));
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (const std::runtime_error& ex)
    {
        QMessageBox::information(this, "Runtime error", ex.what());
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (...)
    {
        QMessageBox::information(this, "Unexpected error", "Unexpected error, the program terminates");
        close();
    }
}

/// Parameter:
/// Return:
/// Action: Emboss transformation.
///         Sets progress bar.
///         Disables UI elements.
///         Run the transformation.
///         Set the modified image and the data in the table.
///         Enables UI elements.
void MyMainWindow::emboss_triggered()
{
    try
    {
        _progressBar->setMinimum(_backend->progress_min());
        _progressBar->setMaximum(_backend->progress_max());

        TransformInfo info;
        disable_ui();
        enable_cancel();
        QImage* result = _backend->emboss(info);
        _myWidget->set_modified(result);
        _myWidget->add_info(info);

        if (result->isNull())
        {
            enable_ui();
            disable_cancel();
            disable_save();
        }
        else
        {
            enable_save();
            enable_ui();
            disable_cancel();
        }
    }
    catch (const OpenCLException& ex)
    {
        QMessageBox::information(this, "OpenCL error",
                                 QString(ex.what()) + ". Code: " +
                                 QString::number(ex.error_code()));
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (const std::runtime_error& ex)
    {
        QMessageBox::information(this, "Runtime error", ex.what());
        disable_save();
        enable_ui();
        disable_cancel();
        return;
    }
    catch (...)
    {
        QMessageBox::information(this, "Unexpected error", "Unexpected error, the program terminates");
        close();
    }
}

/// Parameter:
/// Return:
/// Action: Listener for zoom in button.
void MyMainWindow::zoom_in_triggered()
{
    _myWidget->zoom_in();
}

/// Parameter:
/// Return:
/// Action:  Listener for zoom out button.
void MyMainWindow::zoom_out_triggered()
{
    _myWidget->zoom_out();
}

/// Parameter:
/// Return:
/// Action:  Listener for zoom reset button.
void MyMainWindow::zoom_reset_triggered()
{
    _myWidget->zoom_reset();
}

/// Parameter:
/// Return:
/// Action:  Listener for swap button.
void MyMainWindow::swap_triggered()
{
    try
    {
        _backend->swap();
        _myWidget->swap();
    }
    catch (const OpenCLException& ex)
    {
        QMessageBox::information(this, "OpenCL error",
                                 QString(ex.what()) + ". Code: " +
                                 QString::number(ex.error_code()));
        return;
    }
    catch (const std::runtime_error& ex)
    {
        QMessageBox::information(this, "Runtime error", ex.what());
        return;
    }
    catch (...)
    {
        QMessageBox::information(this, "Unexpected error", "Unexpected error, the program terminates");
        close();
    }
}

/// Parameter:
/// Return:
/// Action: Listener for finished signal.
///         Shows a messagebox about the transformation.
void MyMainWindow::finished(double time)
{
    //setUpdatesEnabled(false);

    if (__canTransform)
        QMessageBox::information(this, "Finished", "Transformation successfully finished in: " +
                                 QString::number(time / 1000) + "seconds");
    else
        QMessageBox::information(this, "Aborted", "Transformation canceled");

    //setUpdatesEnabled(true);
    //update();
}

/// Parameter: v: progress bar value
/// Return:
/// Action: Sets the progress bar to the value
void MyMainWindow::update_progress_bar(int v)
{
    _progressBar->setUpdatesEnabled(false);
    _progressBar->setValue(v);
    _progressBar->setUpdatesEnabled(true);
    _progressBar->update();
}

/// Parameter:
/// Return:
/// Action: Listener for the cancel button.
void MyMainWindow::cancel_clicked()
{
    __canTransform = false;
}

/// Parameter:
/// Return:
/// Action: Constructor
///         Constructs the window, sets the properties.
MyMainWindow::MyMainWindow(QWidget *parent) : QMainWindow(parent)
{
    _backend = new Backend();
    connect(_backend, SIGNAL(finished(double)), this, SLOT(finished(double)));

    setup_menu();
    setup_toolbar();

    _myWidget = new MyWidget();
    setCentralWidget(_myWidget);
    _progressBar = new QProgressBar;

    _label = new QLabel("No platform set, using sequential algorithm");

    _cancelButton = new QPushButton("Cancel");
    _cancelButton->setEnabled(false);
    connect(_cancelButton, SIGNAL(clicked()), this, SLOT(cancel_clicked()));

    statusBar()->addPermanentWidget(_progressBar, 0);
    statusBar()->addPermanentWidget(_cancelButton, 0);
    statusBar()->addWidget(_label);
    connect(_backend, SIGNAL(progress_to_gui(int)), this, SLOT(update_progress_bar(int)));

    qApp->installEventFilter(this);

    _openCLDialog = 0;

    setWindowTitle("Image manipulation");
}

/// Parameter: o: sender object
///            e: event
/// Return:
/// Action: We install an event filter on the main window, to prevent the image viewer's scrollbar
///         to move up-down, left-right.
///         We capture every wheel event, and forward it to the central widget.
bool MyMainWindow::eventFilter(QObject *o, QEvent *e)
{
    if (e->type() == QEvent::Wheel)
    {
        QWheelEvent* we = static_cast<QWheelEvent*>(e);
        _myWidget->wheelEvent(we);
        return true;
    }

    return false;
}
